Construct binary search tree from preorder traversal

Time: O(N); Space: O(H); medium

Return the root node of a binary search tree that matches the given preorder traversal.

(Recall that a binary search tree is a binary tree where for every node, any descendant of node.left has a value < node.val, and any descendant of node.right has a value > node.val. Also recall that a preorder traversal displays the value of the node first, then traverses node.left, then traverses node.right.)

It’s guaranteed that for the given test cases there is always possible to find a binary search tree with the given requirements.

Example 1:

Input: preorder = [8,5,1,7,10,12]

Output: {TreeNode} [8,5,10,1,7,null,12]

Constraints:

  • 1 <= preorder.length <= 100

  • 1 <= preorder[i] <= 10^8

  • The values of preorder are distinct.

[1]:
class TreeNode(object):
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

Auxiliary Tools¶

[2]:
from graphviz import Graph

class TreeTasks(object):
    def visualize_tree(self, tree):
        def add_nodes_edges(tree, dot=None):
            # Create Graph (not Digraph) object
            if dot is None:
                dot = Graph()
                dot.node(name=str(tree), label=str(tree.val))
            # Add nodes
            if tree.left:
                dot.node(name=str(tree.left), label="."+str(tree.left.val))
                dot.edge(str(tree), str(tree.left))
                dot = add_nodes_edges(tree.left, dot=dot)
            if tree.right:
                dot.node(name=str(tree.right), label=str(tree.right.val)+".")
                dot.edge(str(tree), str(tree.right))
                dot = add_nodes_edges(tree.right, dot=dot)
            return dot
        # Add nodes recursively and create a list of edges
        dot = add_nodes_edges(tree)
        # Visualize the graph
        display(dot)
        return dot

1. Recursion

[3]:
class Solution1(object):
    """
    Time: O(N)
    Space: O(H)
    """
    def bstFromPreorder(self, preorder):
        """
        :type preorder: List[int]
        :rtype: TreeNode
        """
        def bstFromPreorderHelper(preorder, left, right, index):
            if index[0] == len(preorder) or \
               preorder[index[0]] < left or \
               preorder[index[0]] > right:
                return None

            root = TreeNode(preorder[index[0]])
            index[0] += 1

            root.left = bstFromPreorderHelper(preorder, left, root.val, index)
            root.right = bstFromPreorderHelper(preorder, root.val, right, index)

            return root

        return bstFromPreorderHelper(preorder, float("-inf"), float("inf"), [0])
[4]:
s = Solution1()

preorder = [8,5,1,7,10,12]
tree = s.bstFromPreorder(preorder)
t = TreeTasks()
dot = t.visualize_tree(tree)
../../_images/topics_tree_1008_construct_binary_search_tree_from_preorder_traversal_[O(N),O(H),med]_6_0.svg